from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from SocketServer import ForkingMixIn, ThreadingMixIn
import threading
from metadata import albumcollection as ac

import os, cgi, shutil, sys
import mimetypes
import posixpath

import logging

log = logging.getLogger("photoshare.client.server")


ALBUM_PREFIX = "/album/"
PHOTO_PREFIX = "/photo/"
SERVE_PREFIX = "/serve/"

class ForkingHTTPServer(ForkingMixIn, HTTPServer):
    pass

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    pass

class DefaultHTTPServer(HTTPServer):
    pass

class PhotoshareHandler(BaseHTTPRequestHandler):
    def write_json_headers(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()

    def handle_discover(self, head = False):
        self.write_json_headers()
        if not head:
            json = ac.tojson()
            self.wfile.write(json)

    def handle_album(self, head = False):
        aname = self.path[len(ALBUM_PREFIX):]
        album = ac.by_name(aname, strict = True)
        if album:
            self.write_json_headers()
            if not head:
                self.wfile.write(album.tojson())
                
        else:
            self.send_error(404, "Resource not found")
            return

    def handle_photo(self, head = False):
        photoid = self.path[len(PHOTO_PREFIX):]
        photo = ac.photo_by_id(photoid)
        if photo:
            self.write_json_headers()
            if not head:
                self.wfile.write(photo.tojson())
        else:
            self.send_error(404, "Resource not found")
            return

    def send_photo_file(self, path, head = False):
        f = None
        mode = 'rb'
        try:
            f = open(path, mode)
            print "Opened file %s" % path
        except IOError:
            self.send_error(404, "File not found")
            return None
        self.send_response(200)

        base, ext = posixpath.splitext(path)
        if ext in mimetypes.types_map:
            mtype = mimetypes.types_map[ext]
        else:
            mtype = "application/octet-stream"
        self.send_header("Content-type", mtype)
        fs = os.fstat(f.fileno())
        self.send_header("Content-Length", str(fs[6]))
        self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
        #self.send_header("Content-Disposition", "attachment; filename=%s" % os.path.basename(path))
        self.end_headers()
        
        if not head:
            self.copyfile(f, self.wfile)
        f.close()

    def handle_serve(self, head = False):
        photoid = self.path[len(PHOTO_PREFIX):]
        path = ac.path_for_photo_id(photoid)
        if path:
            self.send_photo_file(path, head)
        else:
            self.send_error(404, "Resource not found")
            return

    def process_request(self, head  = False):
        self.log_error("Processing request for url %s" % self.path)
        if self.path == "/discover":
            self.handle_discover(head)
            return True

        routes = {ALBUM_PREFIX : self.handle_album,
                  PHOTO_PREFIX : self.handle_photo,
                  SERVE_PREFIX : self.handle_serve}

        
        for k in routes:
            if self.path.startswith(k):
                routes[k](head)
                return True
        
        self.send_error(500, "Cannot handle request")
        return False
                
    def do_GET(self):
        return self.process_request(head = False)

    def do_HEAD(self):
        return self.process_request(head = True)

    def copyfile(self, source, outputfile):
        shutil.copyfileobj(source, outputfile)

    



            



        
